import json

import requests

from dao.mongo_dao.wechat_login_dao import find_wechat_login
from utils.health_utils import build_sos_keyword

from utils.logger_util import logger
from client.redis_client import r


class WechatTokenManager:
    key = "wx30df574444fa09a8"
    secret = "c7b5a0196931bea1966c35ea5196f423"

    async def get_token(self, token_error: bool = False):
        # 第一层校验：本地内存检查
        # if not token_error:
        #     redis_token = r.get('templateMessage')
        #     if redis_token is not None:
        #         return redis_token.decode('utf-8')
        # else:
            # 调用微信API获取新token
        new_token, expires_in = await self._fetch_from_wechat()
        # r.set('templateMessage', new_token, ex=expires_in - 200)
        return new_token

    async def _fetch_from_wechat(self):
        url = f"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={self.key}&secret={self.secret}"
        res = requests.get(url).json()
        if 'access_token' not in res:
            logger.error(f"微信接口异常: {res.get('errmsg')}")
        return res['access_token'], res['expires_in']


async def send_template_message(data, token):
    # 首次尝试获取

    response = requests.post(
        f"https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={token}",
        json=data
    ).json()

    # 处理token过期场景
    if token is None:
        # 强制清除本地缓存触发刷新
        token_manager = WechatTokenManager()
        token = await token_manager.get_token()
        return await send_template_message(data, token)  # 重试
    logger.info(f'发送微信公众号模版消息{data}，返回{response}')
    return response


def build_wechat_message_data(miniprogram: dict = None, url: str = "", openid_list: list = [], keyword_data: dict = {},
                              template_id: str = None):
    message_list = []
    for openid in openid_list:
        data = {
            "touser": openid,  # 接收者用户openid
            "data": keyword_data,
            "template_id": template_id
        }
        if miniprogram is not None:
            data['miniprogram'] = miniprogram
        if url is not None:
            data['url'] = url
        message_list.append(data)
    return message_list


async def alert_data(data: dict, alert: str):
    source = json.loads(r.hget('state_' + data['device_id'], 'source'))
    openid_list = find_wechat_login(str(source['departId']))
    token_manager = WechatTokenManager()
    token = await token_manager.get_token()
    sos_keyword = build_sos_keyword(f'项目{source["departName"]}-{source["name"]}{alert}',
                                    data['timestamp'])
    sos_message_data = build_wechat_message_data(keyword_data=sos_keyword,
                                                 openid_list=openid_list,
                                                 template_id='CFAqdHDzCHRPGbJd0lifZ8oEERoNTuZUI3c2MBzB_Is')
    for message in sos_message_data:
        await send_template_message(message, token)